package com.cloud.hotline.api.service.impl;

import java.sql.Date;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BatchPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.cloud.hotline.api.bean.HotlineImportForm;
import com.cloud.hotline.api.consts.HotLineConsts;
import com.cloud.hotline.api.entity.TcDicUnitType;
import com.cloud.hotline.api.entity.ToHotlineRecord;
import com.cloud.hotline.api.entity.ToHotlineRevisitRecord;
import com.cloud.hotline.api.entity.ToHotlineStreetRecord;
import com.cloud.hotline.api.entity.ToHotlineUnitRecord;
import com.cloud.hotline.api.mapper.TcDicUnitTypeMapper;
import com.cloud.hotline.api.mapper.ToHotlineRecordMapper;
import com.cloud.hotline.api.service.HotlineService;
import com.cloud.hotline.common.utils.DateHelper;

@Service
@Transactional
public class HotlineServiceImpl implements HotlineService {

	private static List<String> unitNameCache = null;
	private static Map<String, TcDicUnitType> unitTypeCache = null;

	private static Lock lock = new ReentrantLock();
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private ToHotlineRecordMapper toHotlineRecordMapper;

	@Autowired
	private TcDicUnitTypeMapper tcDicUnitTypeMapper;

	@Override
	public void initUnitTypes(List<TcDicUnitType> unitTypes) {
		Set<TcDicUnitType> types = new HashSet<TcDicUnitType>(unitTypes);
		final List<TcDicUnitType> batchTypes = new ArrayList<TcDicUnitType>(types);

		jdbcTemplate.batchUpdate("insert into tc_dic_unit_type (unit_name, origin_unit_name) values (?, ?)",
				new BatchPreparedStatementSetter() {
					@Override
					public void setValues(PreparedStatement ps, int i) throws SQLException {
						TcDicUnitType type = batchTypes.get(i);
						ps.setString(1, type.getUnitName());
						ps.setString(2, type.getOriginUnitName());
					}

					@Override
					public int getBatchSize() {
						return batchTypes.size();
					}
				});
	}

	@Override
	public void importData(HotlineImportForm records) {
		List<ToHotlineRecord> rs = new ArrayList<ToHotlineRecord>();
		List<String> yesswNums = new ArrayList<String>(); // 市长热线编号
		if (records.getRevisitRecords().size() > 0) {
			// 诉求三率：市级回访
			List<ToHotlineRevisitRecord> cityRevisits = records.getRevisitRecords();
			for (ToHotlineRevisitRecord rv : cityRevisits) {
				ToHotlineRecord r = new ToHotlineRecord(rv);
				replaceUnitInfo(r);
				rs.add(r);
				yesswNums.add(r.getYesswNum());
			}
		} else if (records.getStreetRecords().size() > 0) {
			// 街道承办
			List<ToHotlineStreetRecord> cityRevisits = records.getStreetRecords();
			java.util.Date stateDate = DateHelper.getDateBeforeOrAfterHours(
					DateHelper.strToFormatDate(records.getStart(), "yyyy-MM-dd HH:mm"), 21);
			for (ToHotlineStreetRecord cr : cityRevisits) {
				// 导入街道承办时选择的开始时间+21小时
				cr.setStateDate(stateDate);
				ToHotlineRecord r = new ToHotlineRecord(cr);
				replaceUnitInfo(r);
				rs.add(r);
				yesswNums.add(r.getYesswNum());
			}
		} else if (records.getUnitRecords().size() > 0) {
			List<ToHotlineUnitRecord> unitRecords = records.getUnitRecords();
			for (ToHotlineUnitRecord ur : unitRecords) {
				if (records.getType() == 0) {
					// 诉求三率 ：区级回访
					ur.setDataTypeId(HotLineConsts.DATA_TYPE_AREA_REVISIT);
					ur.setStateDate(ur.getFeedbackTime());
				} else {
					// 部门承办
					ur.setDataTypeId(HotLineConsts.DATA_TYPE_UNIT_UNDERTAKE);
					java.util.Date stateDate = DateHelper.getDateBeforeOrAfterHours(
							DateHelper.strToFormatDate(records.getStart(), "yyyy-MM-dd HH:mm"), 21);
					ur.setStateDate(stateDate);
				}
				
				ToHotlineRecord r = new ToHotlineRecord(ur);
				replaceUnitInfo(r);
				rs.add(r);
				yesswNums.add(r.getYesswNum());
			}
		}
		// 【市长热线编号】作为唯一标识 -- 新数据覆盖旧数据
		List<ToHotlineRecord> exitRecords = toHotlineRecordMapper.checkRecordExists(yesswNums);
		List<ToHotlineRecord> batchInsertRecords = new ArrayList<ToHotlineRecord>();
		List<ToHotlineRecord> batchUpdateRecords = new ArrayList<ToHotlineRecord>();

		for (ToHotlineRecord r : rs) {
			boolean include = false;
			for (ToHotlineRecord e : exitRecords) {
				if (r.getYesswNum().equals(e.getYesswNum())) {
					r.setRecordId(e.getRecordId());
					include = true;
					break;
				}
			}
			if (include) {
				batchUpdateRecords.add(r);
			} else {
				batchInsertRecords.add(r);
			}
		}

		if (batchUpdateRecords.size() > 0) {
			final List<ToHotlineRecord> list = batchUpdateRecords;
			// 批量更新
			jdbcTemplate.batchUpdate(
					"update to_hotline_record set data_type_id = ?, yessw_num = ?, dispatch_date = ?, record_type_name = ?, reporter_name = ?, "
							+ "record_desc = ?, desc_short = ?, address = ?, call_num = ?, dispatch_type = ?, receive_unit_name = ?, record_state_name = ?, nonstate_reason = ?, "
							+ "street_receive_date = ?, unit_receive_date = ?, revisit_date = ?, unit_name = ?, record_handle_desc = ?, answer_flag_name = ?, "
							+ "finish_flag_name = ?, pleased_flag_name = ?, rec_disp_num = ?, coor_x = ?, coor_y = ?, unit_type = ?, state_date = ?, last_modify_time = now(),"
							+ "city_revisit_date = ?, city_pleased_flag_name = ?, city_finish_flag_name = ? where record_id = ?",
					new BatchPreparedStatementSetter() {
						@Override
						public void setValues(PreparedStatement ps, int i) throws SQLException {
							ToHotlineRecord r = list.get(i);
							ps.setInt(1, r.getDataTypeId());
							ps.setString(2, r.getYesswNum());
							if (null == r.getDispatchDate()) {
								ps.setTimestamp(3, null);
							} else {
								ps.setTimestamp(3, new Timestamp(r.getDispatchDate().getTime()));
							}
							ps.setString(4, r.getRecordTypeName());
							ps.setString(5, r.getReporterName());
							ps.setString(6, r.getRecordDesc());
							ps.setString(7, r.getDescShort());
							ps.setString(8, r.getAddress());
							ps.setString(9, r.getCallNum());
							ps.setString(10, r.getDispatchType());
							ps.setString(11, r.getReceiveUnitName());
							ps.setString(12, r.getRecordStateName());
							ps.setString(13, r.getNonstateReason());
							if (null == r.getStreetReceiveDate()) {
								ps.setTimestamp(14, null);
							} else {
								ps.setTimestamp(14, new Timestamp(r.getStreetReceiveDate().getTime()));
							}
							if (null == r.getUnitReceiveDate()) {
								ps.setTimestamp(15, null);
							} else {
								ps.setTimestamp(15, new Timestamp(r.getUnitReceiveDate().getTime()));
							}
							if (null == r.getRevisitDate()) {
								ps.setTimestamp(16, null);
							} else {
								ps.setTimestamp(16, new Timestamp(r.getRevisitDate().getTime()));
							}
							ps.setString(17, r.getUnitName());
							ps.setString(18, r.getRecordHandleDesc());
							ps.setString(19, r.getAnswerFlagName());
							ps.setString(20, r.getFinishFlagName());
							ps.setString(21, r.getPleasedFlagName());
							ps.setString(22, r.getRecDispNum());
							if (null == r.getCoorX()) {
								ps.setFloat(23, 0.0f);
							} else {
								ps.setFloat(23, r.getCoorX());
							}
							if (null == r.getCoorY()) {
								ps.setFloat(24, 0.0f);
							} else {
								ps.setFloat(24, r.getCoorY());
							}
							if (r.getUnitName().indexOf("街道") >= 0) {
								ps.setInt(25, 0);
							} else {
								ps.setInt(25, 1);
							}
							ps.setDate(26, new Date(r.getStateDate().getTime()));
							
							if (null == r.getCityRevisitDate()) {
								ps.setTimestamp(27, null);
							} else {
								ps.setTimestamp(27, new Timestamp(r.getCityRevisitDate().getTime()));
							}
							ps.setString(28, r.getCityPleasedFlagName());
							ps.setString(29, r.getCityFinishFlagName());
							
							ps.setInt(30, r.getRecordId());
						}

						@Override
						public int getBatchSize() {
							return list.size();
						}
					});
		}

		if (batchInsertRecords.size() > 0) {
			final List<ToHotlineRecord> list = batchInsertRecords;
			// 批量导入信息
			jdbcTemplate.batchUpdate(
					"insert into to_hotline_record (data_type_id, yessw_num, dispatch_date, record_type_name, reporter_name, "
							+ "record_desc, desc_short, address, call_num, dispatch_type, receive_unit_name, record_state_name, nonstate_reason, "
							+ "street_receive_date, unit_receive_date, revisit_date, unit_name, record_handle_desc, answer_flag_name, "
							+ "finish_flag_name, pleased_flag_name, rec_disp_num, coor_x, coor_y, unit_type, state_date, city_revisit_date, city_pleased_flag_name, "
							+ "city_finish_flag_name, insert_time, last_modify_time, delete_flag, delete_time"
							+ ") values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, now(), now(), 0, null)",
					new BatchPreparedStatementSetter() {
						@Override
						public void setValues(PreparedStatement ps, int i) throws SQLException {
							ToHotlineRecord r = list.get(i);
							ps.setInt(1, r.getDataTypeId());
							ps.setString(2, r.getYesswNum());
							if (null == r.getDispatchDate()) {
								ps.setTimestamp(3, null);
							} else {
								ps.setTimestamp(3, new Timestamp(r.getDispatchDate().getTime()));
							}
							ps.setString(4, r.getRecordTypeName());
							ps.setString(5, r.getReporterName());
							ps.setString(6, r.getRecordDesc());
							ps.setString(7, r.getDescShort());
							ps.setString(8, r.getAddress());
							ps.setString(9, r.getCallNum());
							ps.setString(10, r.getDispatchType());
							ps.setString(11, r.getReceiveUnitName());
							ps.setString(12, r.getRecordStateName());
							ps.setString(13, r.getNonstateReason());
							if (null == r.getStreetReceiveDate()) {
								ps.setTimestamp(14, null);
							} else {
								ps.setTimestamp(14, new Timestamp(r.getStreetReceiveDate().getTime()));
							}
							if (null == r.getUnitReceiveDate()) {
								ps.setTimestamp(15, null);
							} else {
								ps.setTimestamp(15, new Timestamp(r.getUnitReceiveDate().getTime()));
							}
							if (null == r.getRevisitDate()) {
								ps.setTimestamp(16, null);
							} else {
								ps.setTimestamp(16, new Timestamp(r.getRevisitDate().getTime()));
							}
							ps.setString(17, r.getUnitName());
							ps.setString(18, r.getRecordHandleDesc());
							ps.setString(19, r.getAnswerFlagName());
							ps.setString(20, r.getFinishFlagName());
							ps.setString(21, r.getPleasedFlagName());
							ps.setString(22, r.getRecDispNum());
							if (null == r.getCoorX()) {
								ps.setFloat(23, 0.0f);
							} else {
								ps.setFloat(23, r.getCoorX());
							}
							if (null == r.getCoorY()) {
								ps.setFloat(24, 0.0f);
							} else {
								ps.setFloat(24, r.getCoorY());
							}
							ps.setInt(25, r.getUnitType());
							ps.setTimestamp(26, new Timestamp(r.getStateDate().getTime()));
							if (null == r.getCityRevisitDate()) {
								ps.setTimestamp(27, null);
							} else {
								ps.setTimestamp(27, new Timestamp(r.getCityRevisitDate().getTime()));
							}
							ps.setString(28, r.getCityPleasedFlagName());
							ps.setString(29, r.getCityFinishFlagName());
						}

						@Override
						public int getBatchSize() {
							return list.size();
						}
					});
		}

	}

	@Override
	public List<String> listUnitNames() {
		if (null == unitNameCache) {
			lock.lock();
			try {
				if (null == unitNameCache)
					unitNameCache = jdbcTemplate.queryForList(
							"select unit_name from tc_dic_unit_type union all select origin_unit_name from tc_dic_unit_type",
							String.class);
			} finally {
				lock.unlock();
			}
		}
		return unitNameCache;
	}

	private void replaceUnitInfo(ToHotlineRecord record) {
		if (null == unitTypeCache) {
			lock.lock();
			try {
				if (null == unitTypeCache) {
					List<TcDicUnitType> types = tcDicUnitTypeMapper.selectAll();
					Map<String, TcDicUnitType> cache = new HashMap<String, TcDicUnitType>();
					for(TcDicUnitType t : types){
						cache.put(t.getOriginUnitName(), t);
						cache.put(t.getUnitName(), t);
					}
					unitTypeCache = cache;
				}
			} finally {
				lock.unlock();
			}
		}
		TcDicUnitType u = unitTypeCache.get(record.getUnitName());
		if(null != u){
			record.setUnitName(u.getUnitName());
			record.setUnitType(u.getUnitTypeId());
		}
	}
}
